package com.haoxuer.discover.user.rest.resource;

import com.haoxuer.discover.rest.base.ResponseObject;
import com.haoxuer.discover.user.data.enums.SecurityType;
import com.haoxuer.discover.user.data.request.UpdatePasswordRequest;
import com.haoxuer.discover.user.oauth.api.OauthHandler;
import com.haoxuer.discover.user.oauth.domain.OauthResponse;
import com.haoxuer.discover.user.oauth.domain.TokenResponse;
import com.haoxuer.discover.user.utils.CodeCatalog;
import com.haoxuer.discover.user.utils.SecurityUtil;
import com.haoxuer.discover.user.utils.UserUtils;
import com.haoxuer.discover.user.word.AdaptiveRandomWordFactory;
import com.haoxuer.discover.plug.data.service.CodeService;
import com.haoxuer.discover.data.core.Finder;
import com.haoxuer.discover.user.rest.api.UserHandler;
import com.haoxuer.discover.user.data.dao.UserAccountDao;
import com.haoxuer.discover.user.data.dao.UserInfoDao;
import com.haoxuer.discover.user.data.dao.UserOauthConfigDao;
import com.haoxuer.discover.user.data.dao.UserOauthTokenDao;
import com.haoxuer.discover.user.data.dao.UserVerificationDao;
import com.haoxuer.discover.user.data.entity.UserAccount;
import com.haoxuer.discover.user.data.entity.UserInfo;
import com.haoxuer.discover.user.data.entity.UserOauthToken;
import com.haoxuer.discover.user.data.entity.UserVerification;
import com.haoxuer.discover.user.rest.domain.request.CheckPhoneCodeRequest;
import com.haoxuer.discover.user.rest.domain.request.SendCodeRequest;
import com.haoxuer.discover.user.rest.domain.request.UserChangePasswordRequest;
import com.haoxuer.discover.user.rest.domain.request.UserChangePhoneRequest;
import com.haoxuer.discover.user.rest.domain.request.UserLoginCodeRequest;
import com.haoxuer.discover.user.rest.domain.request.UserLoginOatuthRequest;
import com.haoxuer.discover.user.rest.domain.request.UserLoginRequest;
import com.haoxuer.discover.user.rest.domain.request.UserRegisterCodeRequest;
import com.haoxuer.discover.user.rest.domain.request.UserRegisterOatuthRequest;
import com.haoxuer.discover.user.rest.domain.request.UserResetPasswordRequest;
import com.haoxuer.discover.user.rest.domain.request.UserUpdateRequest;
import com.haoxuer.discover.user.rest.domain.response.UserResponse;
import com.haoxuer.discover.user.data.enums.AccountType;
import com.haoxuer.discover.user.rest.vo.SendCodeVo;

import java.util.Calendar;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * Created by ada on 2017/6/29.
 */

@Scope("prototype")
@Transactional
@Component
public class UserResource implements UserHandler {


  @Autowired
  UserVerificationDao verificationDao;

  @Autowired
  UserAccountDao accountDao;

  @Autowired
  UserInfoDao userInfoDao;

  @Autowired
  UserOauthConfigDao configDao;

  @Autowired
  CodeService codeService;


  @Autowired
  UserOauthTokenDao oauthTokenDao;

  public SendCodeVo validate(Date lastDate) {
    SendCodeVo result = new SendCodeVo();
    Long time = checkDate(lastDate);
    if (time < 5 * 60 * 1000) {
      result.setCode(-1);
    }
    return result;
  }

  public SendCodeVo check(Date lastDate) {
    SendCodeVo result = new SendCodeVo();
    Long time = checkDate(lastDate);
    if (time > 5 * 60 * 1000) {
      result.setCode(-1);
    }
    return result;
  }

  private Long checkDate(Date lastDate) {
    if (lastDate == null) {
      Calendar calendar = Calendar.getInstance();
      lastDate = calendar.getTime();
    }
    return System.currentTimeMillis() - lastDate.getTime();
  }

  public SendCodeVo send(String template, String phone) {
    SendCodeVo result = new SendCodeVo();

    AdaptiveRandomWordFactory f = new AdaptiveRandomWordFactory();
    f.setMinLength(4);
    f.setMaxLength(4);
    f.setCharacters("1234567890");
    String vcode = "" + f.getNextWord();
    result.setSendCode(vcode);
    boolean res = codeService.sendCode(vcode, template, phone);
    if (!res) {
      result.setCode(-1);
    }
    return result;
  }


  @Override
  public ResponseObject sendCode(SendCodeRequest request) {
    ResponseObject result = new ResponseObject();

    Integer catalog = CodeCatalog.catalog(request.getCatalog());
    if (catalog == null) {
      result.setCode(-1);
      result.setMsg("参数异常");
      return result;
    }
    if (request.getCatalog().equals("register") || request.getCatalog().equals("changePhone")) {
      UserAccount userAccount = findAccount(request.getPhone());
      if (userAccount != null) {
        result.setCode(-2);
        result.setMsg("该手机号已经注册过了");
        return result;
      }
    }
    if ("reset".equals(request.getCatalog())) {
      if (accountDao.findByPhone(request.getPhone()) == null) {
        result.setCode(-3);
        result.setMsg("该手机号未注册！");
        return result;
      }
    }

    UserVerification verification = verificationDao.findByName(request.getPhone(), catalog);
    if (verification != null) {
      Date lastDate = verification.getLastDate();
      SendCodeVo validateCode = validate(lastDate);
      if (validateCode.getCode() != 0) {
        result.setCode(-3);
        result.setMsg("验证码还没有过期");
        return result;
      }
      SendCodeVo send = send(request.getCatalog(), request.getPhone());
      if (send.getCode() != 0) {
        result.setCode(-1);
        result.setMsg("发送验证码失败");
        return result;
      }
      verification.setName(request.getPhone());
      verification.setCode(send.getSendCode());
      verification.setLastDate(new Date());
      verificationDao.update(verification);
    } else {
      UserVerification v = new UserVerification();
      SendCodeVo send = send(request.getCatalog(), request.getPhone());
      if (send.getCode() != 0) {
        result.setCode(-1);
        result.setMsg("发送验证码失败");
        return result;
      }
      v.setName(request.getPhone());
      v.setCode(send.getSendCode());
      v.setCatalog(catalog);
      verificationDao.save(v);
    }
    return result;
  }

  @Override
  public UserResponse loginByCode(UserLoginCodeRequest request) {
    UserResponse result = new UserResponse();


    if (checkCode(request.getPhone(), request.getCode(), 2, result)) {
      return result;
    }

    UserInfo user = null;

    UserAccount userAccount = findAccount(request.getPhone());
    if (userAccount == null) {
      user = new UserInfo();
      user.setName("");
      user.setLoginSize(0);
      user.setLastDate(new Date());
      user.setAddDate(new Date());
      user.setAvatar("");
      user.setPhone(request.getPhone());
      userInfoDao.save(user);


      userAccount = new UserAccount();
      AdaptiveRandomWordFactory factory = new AdaptiveRandomWordFactory();
      factory.setMinLength(6);
      factory.setMaxLength(6);
      factory.setCharacters("1234567890");
      String password = "" + factory.getNextWord();

      SecurityUtil util = new SecurityUtil();
      userAccount.setSalt(util.getSalt());
      userAccount.setPassword(util.entryptPassword(password));
      userAccount.setUsername(request.getPhone());
      userAccount.setAccountType(AccountType.Phone);
      userAccount.setAddDate(new Date());
      userAccount.setLoginSize(0);
      userAccount.setLastDate(new Date());
      userAccount.setUser(user);
      userAccount = accountDao.save(userAccount);

      /**
       * 发送手机注册时候的密码
       */
      codeService.sendCode(password, "init", request.getPhone());
    }
    userAccount.setLastDate(new Date());

    user = userAccount.getUser();
    handleUserInfo(result, user);

    return result;
  }

  private UserAccount findAccount(String phone) {
    Finder finder = Finder.create();
    finder.append("from UserAccount u where u.username=:username");
    finder.setParam("username", phone);
    return accountDao.findOne(finder);
  }

  @Override
  public UserResponse registerByCode(UserRegisterCodeRequest request) {
    UserResponse result = new UserResponse();

    if (request.getPhone() == null) {
      result.setCode(-1);
      result.setMsg("手机号不能为空");
      return result;
    }
    if (checkCode(request.getPhone(), request.getCode(), 1, result)) {
      return result;
    }


    UserInfo user = null;
    UserAccount userAccount = findAccount(request.getPhone());
    if (userAccount != null) {
      result.setCode(-5);
      result.setMsg("改手机号已经注册过了");
      return result;
    }
    user = new UserInfo();
    user.setName(name(request.getPhone()));
    user.setLoginSize(0);
    user.setLastDate(new Date());
    user.setAddDate(new Date());
    user.setAvatar("");
    user.setPhone(request.getPhone());
    userInfoDao.save(user);


    userAccount = new UserAccount();
    SecurityUtil util = new SecurityUtil();
    userAccount.setSalt(util.getSalt());
    userAccount.setPassword(util.entryptPassword(request.getPassword()));
    userAccount.setUsername(request.getPhone());
    userAccount.setAccountType(AccountType.Phone);
    userAccount.setAddDate(new Date());
    userAccount.setLoginSize(0);
    userAccount.setLastDate(new Date());
    userAccount.setUser(user);
    userAccount = accountDao.save(userAccount);
    handleUserInfo(result, user);

    return result;
  }

  public String name(String phone) {
    if (phone == null) {
      return "用户";
    }
    if (phone.length() > 10) {
      return phone.substring(0, 3) + "****" + phone.substring(7);
    } else {
      return phone;
    }

  }

  public static void main(String[] args) {
    UserResource resource = new UserResource();
    System.out.println(resource.name("18229060103"));
  }

  private void handleUserInfo(UserResponse result, UserInfo user) {
    if (user == null) {
      return;
    }
    result.setUserToken(UserUtils.getToken(user.getId()));
    result.setName(user.getName());
    result.setAvatar(user.getAvatar());
    result.setPhone(user.getPhone());
  }

  @Override
  public UserResponse login(UserLoginRequest request) {
    UserResponse result = new UserResponse();
    result.setUserToken(UserUtils.getToken(result.getId()));

    return result;
  }

  @Override
  public UserResponse loginOauth(UserLoginOatuthRequest request) {
    UserResponse result = new UserResponse();

    OauthHandler oauthHandler = configDao.id(request.getType());
    if (oauthHandler == null) {
      result.setCode(-1);
      result.setMsg("该登陆方式无效");
      return result;
    }
    TokenResponse response = oauthHandler.getToken(request.getCode());
    if (response == null) {
      result.setCode(-2);
      result.setMsg("链接第三方失败");
      return result;
    }
    if (StringUtils.isEmpty(response.getOpenId())) {
      result.setCode(-3);
      result.setMsg("获取openid失败");
      return result;
    }

    UserOauthToken token = oauthTokenDao.findByOpenId(response.getOpenId(), request.getType());
    if (token != null) {
      Integer size = token.getLoginSize();
      if (size == null) {
        size = 0;
      }
      size++;
      token.setLoginSize(size);
      token.setAccess_token(response.getAccessToken());
      token.setRefresh_token(response.getRefreshToken());
      token.setLastDate(new Date());
      handleUserInfo(result, token.getUser());
    } else {
      if ("none".equals(request.getStrategy())) {
        result.setCode(-2);
        result.setMsg("没有注册，请注册！");
      } else {
        OauthResponse oauthResponse = oauthHandler.login(response.getAccessToken(), response.getOpenId());
        UserInfo userInfo = new UserInfo();
        if (oauthResponse != null) {
          userInfo.setName(oauthResponse.getName());
          userInfo.setAvatar(oauthResponse.getAvatar());
        }
        userInfoDao.save(userInfo);
        token = new UserOauthToken();
        token.setUser(userInfo);
        token.setLoginSize(0);
        token.setUid(response.getOpenId());
        token.setToken_type(request.getType());
        token.setAccess_token(response.getAccessToken());
        oauthTokenDao.save(token);
        handleUserInfo(result, token.getUser());
      }

    }
    return result;
  }


  @Override
  public UserResponse loginOauthOk(UserLoginOatuthRequest request) {
    request.setStrategy("create");
    return loginOauth(request);
  }


  @Override
  public UserResponse registerOauth(UserRegisterOatuthRequest request) {


    UserResponse result = new UserResponse();


    if (checkCode(request.getPhone(), request.getCode(), 3, result)) {
      return result;
    }


    UserInfo user = new UserInfo();
    String openid = "";

    OauthHandler oauthHandler = configDao.id(request.getType());
    if (oauthHandler == null) {
      result.setCode(-1);
      result.setMsg("该登陆方式无效");
      return result;
    }
    OauthResponse response = oauthHandler.login(request.getAccessToken(), request.getOpenId());

    if (response != null) {
      openid = response.getOpenid();
      user.setName(response.getName());
      user.setAvatar(response.getAvatar());
    }
    if (openid == null || openid.length() == 0) {
      result.setCode(-3);
      result.setMsg("链接第三方失败");
      return result;
    }

    UserAccount userAccount = findAccount(request.getPhone());
    if (userAccount == null) {
      user.setPhone(request.getPhone());
      userInfoDao.save(user);
      userAccount = new UserAccount();
      AdaptiveRandomWordFactory factory = new AdaptiveRandomWordFactory();
      factory.setMinLength(6);
      factory.setMaxLength(6);
      factory.setCharacters("1234567890");
      String password = "" + factory.getNextWord();
      SecurityUtil util = new SecurityUtil();
      userAccount.setSalt(util.getSalt());
      userAccount.setPassword(util.entryptPassword(password));
      userAccount.setUsername(request.getPhone());
      userAccount.setAccountType(AccountType.Phone);
      userAccount.setAddDate(new Date());
      userAccount.setLoginSize(0);
      userAccount.setLastDate(new Date());
      userAccount.setUser(user);
      userAccount = accountDao.save(userAccount);

      /**
       * 发送手机注册时候的密码
       */
      codeService.sendCode(password, "init", request.getPhone());
    } else {
      UserInfo dbuser = userAccount.getUser();
      if (dbuser.getAvatar() == null || dbuser.getAvatar().length() < 10) {
        dbuser.setAvatar(user.getAvatar());
      }
      if (dbuser.getName() == null || dbuser.getName().length() < 1) {
        dbuser.setName(user.getName());
      }
      user = dbuser;
    }

    Finder finder = Finder.create();
    finder.append("from UserOauthToken u where u.uid=:uid and u.token_type=:token_type");
    finder.setParam("uid", openid);
    finder.setParam("token_type", request.getType());

    UserOauthToken token = oauthTokenDao.findOne(finder);
    if (token == null) {
      UserOauthToken oauthToken = new UserOauthToken();
      oauthToken.setLoginSize(0);
      oauthToken.setUser(user);
      oauthToken.setUid(openid);
      oauthToken.setToken_type(request.getType());
      oauthTokenDao.save(oauthToken);
    } else {
      user = token.getUser();
    }

    handleUserInfo(result, user);
    return result;
  }

  @Override
  public UserResponse resetPassword(UserResetPasswordRequest request) {

    UserResponse result = new UserResponse();

    if (checkCode(request.getPhone(), request.getCode(), 4, result)) {
      return result;
    }

    UserAccount userAccount = findAccount(request.getPhone());
    if (userAccount == null) {
      result.setMsg("该账号不存在");
      result.setCode(-5);
      return result;
    }
    SecurityUtil util = new SecurityUtil();
    userAccount.setSalt(util.getSalt());
    userAccount.setPassword(util.entryptPassword(request.getPassword()));
    handleUserInfo(result, userAccount.getUser());

    return result;
  }

  @Override
  public ResponseObject changePhone(UserChangePhoneRequest request) {

    ResponseObject result = new ResponseObject();

    Long member = UserUtils.getMember(request.getUserToken());

    if (member == null) {
      result.setCode(-6);
      result.setMsg("非法操作，token不可用");
      return result;
    }

    if (checkCode(request.getPhone(), request.getCode(), 5, result)) {
      return result;
    }


    UserAccount userAccount = findAccount(request.getPhone());
    if (userAccount != null) {
      result.setMsg("该手机号已被使用");
      result.setCode(-5);
      return result;
    }

    UserInfo user = userInfoDao.findById(member);
    if (user == null) {
      result.setMsg("该用户信息不存在");
      result.setCode(-6);
      return result;
    }
    Finder finder = Finder.create();
    finder.append("from UserAccount u where u.user.id=:uid");
    finder.setParam("uid", member);
    UserAccount tempAccount = accountDao.findOne(finder);
    if (tempAccount == null) {
      result.setMsg("该账号不存在");
      result.setCode(-7);
      return result;
    }
    tempAccount.setUsername(request.getPhone());
    user.setPhone(request.getPhone());

    return result;
  }

  @Override
  public boolean checkCode(String phone, String code, Integer type, ResponseObject result) {

    if (code == null) {
      result.setCode(-1);
      result.setMsg("验证码不能为空");
      return true;
    }
    if (phone == null) {
      result.setCode(-1);
      result.setMsg("手机号不能为空");
      return true;
    }
    UserVerification verification = verificationDao.findByName(phone, type);
    if (verification == null) {
      result.setCode(-2);
      result.setMsg("该验证码不可用");
      return true;
    }

    Date lastDate = verification.getLastDate();
    SendCodeVo validateCode = check(lastDate);
    if (validateCode.getCode() != 0) {
      result.setCode(-3);
      result.setMsg("验证码已经过期");
      return true;
    }
    if (!code.equals(verification.getCode())) {
      result.setCode(-4);
      result.setMsg("验证码错误");
      return true;
    }
    return false;
  }

  @Override
  public ResponseObject checkPhoneCode(CheckPhoneCodeRequest request) {
    ResponseObject result = new ResponseObject();

    Integer catalog = CodeCatalog.catalog(request.getType());
    if (catalog == null) {
      result.setCode(-1);
      result.setMsg("参数异常");
      return result;
    }
    checkCode(request.getPhone(), request.getCode(), catalog, result);
    return result;
  }

  @Override
  public ResponseObject changePassword(UserChangePasswordRequest request) {
    ResponseObject result = new ResponseObject();

    Long member = UserUtils.getMember(request.getUserToken());

    if (member == null) {
      result.setCode(-6);
      result.setMsg("非法操作，token不可用");
      return result;
    }
    UserInfo user = userInfoDao.findById(member);

    if (user == null) {
      result.setMsg("该用户信息不存在");
      result.setCode(-6);
      return result;
    }
    UpdatePasswordRequest updateRequest = new UpdatePasswordRequest();
    updateRequest.setSecurityType(SecurityType.account);
    updateRequest.setPassword(request.getPassword());
    updateRequest.setOldPassword(request.getOldPassword());
    updateRequest.setId(user.getId());
    result = userInfoDao.updatePassword(updateRequest);
    return result;
  }

  @Override
  public UserResponse update(UserUpdateRequest request) {
    UserResponse result = new UserResponse();

    Long member = UserUtils.getMember(request.getUserToken());

    if (member == null) {
      result.setCode(-6);
      result.setMsg("非法操作，token不可用");
      return result;
    }
    UserInfo user = userInfoDao.findById(member);
    if (user == null) {
      result.setMsg("该用户信息不存在");
      result.setCode(-6);
      return result;
    }
    if (StringUtils.hasText(request.getName())) {
      user.setName(request.getName());
    }
    if (StringUtils.hasText(request.getAvatar())) {
      user.setAvatar(request.getAvatar());
    }
    handleUserInfo(result, user);
    return result;
  }
}
